<template>
  <Repl
    v-if="showRepl"
    ref="replRef"
    theme="dark"
    :store="store"
    :editor="Monaco"
    :clearConsole="false"
    :showCompileOutput="true"
    :showTsConfig="false"
    :previewOptions="previewOptions"
  />
</template>

<script>
import { nextTick, ref, watch } from "vue";
import { Repl, ReplStore } from "@vue/repl";
import Monaco from "@vue/repl/monaco-editor";
import { zlibSync, strToU8, strFromU8 } from "fflate";
import "@vue/repl/style.css";
import { browserHash } from "@/../node_modules/.vite/deps/_metadata.json";
import { resolveRuntimeComp } from "@/components/RuntimeComp";

function utoa(data) {
  const buffer = strToU8(data);
  const zipped = zlibSync(buffer, { level: 9 });
  const binary = strFromU8(zipped, true);
  return btoa(binary);
}
const timestamp = browserHash;

let globalCompStr = "";
const exportStr = "export default";
const compMap = await resolveRuntimeComp();
for (const fileName in compMap) {
  const compStr = compMap[fileName].compStr;
  const codeIndex = compStr.indexOf(exportStr);

  globalCompStr += `app.component('${fileName}',${compStr.slice(
    codeIndex + exportStr.length
  )})\r\n`;
}

export default {
  components: {
    Repl,
  },
  props: {
    codeObj: { type: Object, default: () => ({}) },
  },
  setup(props) {
    const store = ref(null);

    const previewOptions = {
      // headHTML: `
      //   `,
      // bodyHTML: "",
      // placeholderHTML: "",
      customCode: {
        importCode: `
        import { h , resolveComponent } from 'vue';
        import Antd from 'ant-design-vue'`,
        useCode: `
      app.use(Antd)
      ${globalCompStr}
      `,
      },
    };

    const replRef = ref(null);
    async function genStore(codeObj) {
      store.value = new ReplStore({
        serializedState: utoa(JSON.stringify(codeObj)),
        showOutput: true,
        outputMode: "preview",
        defaultVueRuntimeURL:
          "/node_modules/.vite/deps/vue.js?tiemstamp=" + timestamp,
      });
      store.value.setImportMap({
        imports: {
          "ant-design-vue":
            "/node_modules/.vite/deps/ant-design-vue.js?tiemstamp=" + timestamp,
        },
      });
    }

    const showRepl = ref(true);

    genStore({ ...props.codeObj });

    watch(
      () => props.codeObj,
      () => {
        showRepl.value = false;
        store.value = null;
        nextTick(() => {
          genStore({ ...props.codeObj });
          nextTick(() => {
            showRepl.value = true;
          });
        });
      }
    );

    return {
      previewOptions,
      replRef,
      showRepl,
      store,
      Monaco,
    };
  },
};
</script>
